/***********************************
 * name:user_wavedat
 * function:获取被测信号的时域数据和频域数据
 * use:通过调用get_wave_dat_t和get_wave_dat_f两个函数
 * time:2025.5.24
 ***********************************/
#include "user_wavedat.h"
#include "math.h"
/**
 * 
 * 大概估计适合各频段的采样率范围
 * 20000 10khz - 100hz
 * 1000 100hz - 1hz
 * 100 1hz - 0.1hz
 */
/********时域测量变量定义***********/
//过零点信息存储结构体
typedef struct{
    float time[2];//过零点时间 存储第一个过零点时间和最后一个过零点时间
    int compare_bit;//比较位 负到正为 1 正到负为 -1
    int state;//有效过零点状态
    uint16_t num;//过零点数量
}cross_zero;
/**
 * @brief 时域测量下获取当前信号信息
 * @param wave_dat 信号数据结构体
 * @param adc_buffer 采样缓冲区处理之后的还原原始信号幅度的待处理数据数组
 * @return none 
 */
void get_wave_dat_t(wave_t *wave_dat,float *ac_signal,uint32_t SAMPLE_RATE)
{
    /*峰峰值测量*/
    float peak_max = ac_signal[0];//定义最大值
    float peak_min = ac_signal[0];//定义最小值
    for(uint16_t i = 0;i < BUFFER_SIZE;i++)
    {
        //循环遍历找出当前缓冲区最大值和最小值
        if (ac_signal[i] > peak_max) 
        {
            //找出最大值
            peak_max = ac_signal[i];
        } 
        else if (ac_signal[i] < peak_min) 
        {
            //找出最小值
            peak_min = ac_signal[i];
        }
    }
    //获取信号峰峰值
    //wave_dat->wave_peak = mean_filter_add_data(&peak_filter,(float)(peak_max - peak_min)*2);
    wave_dat->wave_peak = peak_max - peak_min - 0.2;
    /*获取信号频率值(过零点检测法)*/

    // 计算信号的平均值（直流分量）
   /* float dc_offset = 0.0f;//定义信号平均值存储变量
    for (int i = 0; i < BUFFER_SIZE; i++) 
    {
        //buffer数据求和
        dc_offset += adc_buffer[i];
    }
    //求出buffer平均值即直流分量
    dc_offset /= BUFFER_SIZE;
    
    //去除直流分量
    //创建新数组用以存储去除直流分量后的数据
    float ac_signal[BUFFER_SIZE] = {0};
    for (int i = 0; i < BUFFER_SIZE; i++) 
    {
        //数据存储,用于后续数据处理
        ac_signal[i] = adc_buffer[i] - dc_offset;
    }*/

    //过零点检测
    //定义零点数据结构体
    cross_zero detect_zero;
    detect_zero.compare_bit = (ac_signal[0]>=0)?1:-1;//过零点比较位初始化
    detect_zero.num = 0;//对buffer第一个元素是否为零点进行判断
    detect_zero.time[0] = -1;
    detect_zero.time[1] = -1;

    //设置阈值以避免噪声造成的误判
    //float threshold = wave_dat->wave_peak * 0.05f; // 5%的峰峰值作为阈值
    int current_bit=0;
    for(int i = 1;i < BUFFER_SIZE;i++)
    {
        //阈值判断
        if(ac_signal[i] > 0) current_bit = 1;
        else if(ac_signal[i] < 0) current_bit = -1;
        //else current_bit = detect_zero.compare_bit;
        //过零点检测
        if(detect_zero.compare_bit != current_bit)
        {
            //过零点数量更新
            detect_zero.num++;
            //过零点位置更新
            if(detect_zero.time[0] == -1)
            {
                // 线性插值算出两个采样点间的零点时间
                int idx = i;
                float y1 = ac_signal[idx - 1], y2 = ac_signal[idx];
                //const float EPS = 1e-6f; 
                //if(y1*y2<0 &&((y2 - y1) > EPS || (y1 - y2) > EPS))
                //{
                    float t_zero = ((-y1) / (y2 - y1)) * (1.0f / (float)SAMPLE_RATE) + ((float)(idx - 1) / (float)SAMPLE_RATE);
                    // 分别存 first_zero_time, last_zero_time
                    //第一个过零点时间
                    detect_zero.time[0] = t_zero;
                //}
            }
            int idx = i;
            float y1 = ac_signal[idx - 1], y2 = ac_signal[idx];
            //const float EPS = 1e-6f; 
            //if(y1*y2<0 &&((y2 - y1) > EPS || (y1 - y2) > EPS))
            //{
                float t_zero = ((-y1) / (y2 - y1)) * (1.0f / (float)SAMPLE_RATE) + ((float)(idx - 1) / (float)SAMPLE_RATE);
                // 分别存 first_zero_time, last_zero_time
                //第一个过零点时间
                detect_zero.time[1] = t_zero;
            //}
            //过零点比较位更新
            detect_zero.compare_bit = current_bit;
        }
        
    }
    //根据过零点进行信号频率计算
    if(detect_zero.num < 2)
    {
        user_printf(&huart1,"freq error!\r\n");
        return;
    }

    float periods = detect_zero.num-1.0f;//半周期数量
    float sample_time = (float)(detect_zero.time[1] - detect_zero.time[0]);
    float frequency = periods / (sample_time * 2.0f);
    //获取信号频率
    wave_dat->wave_freq = frequency;
}
/********频域测量变量定义***********/
arm_cfft_radix4_instance_f32 scfft;//FFT结构体
//高频通道专用FFT数组
float fft_input[BUFFER_SIZE * 2];//FFT 输入数据存储数组
float fft_output[BUFFER_SIZE];//FFT 输出数据存储数组
//低频通道专用FFT数组
float fft_input_1[BUFFER_SIZE * 2];//FFT 输入数据存储数组
float fft_output_1[BUFFER_SIZE];//FFT 输出数据存储数组
/**
 * @brief FFT初始化函数
 * @param none
 * @return none
 */
void user_fft_init(void)
{
    //FFT结构体初始化
    arm_cfft_radix4_init_f32(&scfft,BUFFER_SIZE,0,1);

}
/**
 * @brief 频域测量数据获取函数
 * @param wave_dat 信号数据结构体
 * @param adc_buffer 采样缓冲区处理之后的还原原始信号幅度的待处理数据数组
 * @return none
 */
 void get_wave_dat_f(wave_t *wave_dat,float *ac_signal,float *fft_input,float *fft_output,uint32_t SAMPLE_RATE)
{
    
    //生成FFT输入数据,将浮点数转换为复数类型
    for(uint16_t i = 0;i < BUFFER_SIZE;i++)
    {
        fft_input[i * 2] = ac_signal[i];//实部
        fft_input[i * 2 + 1] = 0;//虚部
    }
    
    //调用FFT进行计算(基4)
    arm_cfft_radix4_f32(&scfft,fft_input);
    //将复数数据转换为实数数据,取模
    arm_cmplx_mag_f32(fft_input,fft_output,BUFFER_SIZE);

    
    //查找最大峰值
    float max_val = 0;
    uint16_t max_idx = 0;
    for (uint16_t i = 1; i < BUFFER_SIZE / 2; i++) 
    {
        if (fft_output[i] > max_val) 
        {
            max_val = fft_output[i];
            max_idx = i;
        }
    }
    //使用插值法提高精度
    float mag_k = fft_output[max_idx];
    float mag_prev = fft_output[max_idx - 1];
    float mag_next = fft_output[max_idx + 1];
    float delta = (mag_next - mag_prev) / (2.0f * (2.0f * mag_k - mag_prev - mag_next));
    //获取FFT反算得到的信号频率
    wave_dat->wave_freq_f = (float)((float)max_idx + delta) * SAMPLE_RATE / (float)BUFFER_SIZE;
    // 计算插值后的主频幅度
    float mag_interpolated = mag_k + (delta / 2.0f) * (mag_next - mag_prev);
    // 归一化幅度
    /*float N = (float)BUFFER_SIZE;
    if (max_idx == 0 || max_idx == BUFFER_SIZE / 2)
    {
        wave_dat->wave_amplitude = mag_interpolated / 100; // 直流分量或奈奎斯特频率
    }
    else
    {
        wave_dat->wave_amplitude = 2.0f * mag_interpolated / 170; // 其他频率分量
    }*/

    // 转换为分贝（dB），参考值为 1.0
    wave_dat->wave_amplitude = 20.0f * log10f(mag_interpolated / 3.07);

}